home *** CD-ROM | disk | FTP | other *** search
- /*
-
- File: hdaccess.c
-
- Copyright (C) 1998-2004 Christophe GRENIER <grenier@cgsecurity.org>
-
- This software is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
- #include <stdio.h>
- #include <sys/stat.h>
- #include <unistd.h> /* lseek, read, write, close */
- #include <string.h>
- #include <fcntl.h> /* open */
- #include <errno.h>
- #ifdef DJGPP
- #include <stdlib.h> /* atexit */
- #include <go32.h> /* dosmemget/put */
- #include <dpmi.h>
- #include <bios.h> /* bios_k* */
- #elif defined(LINUX)
- #include <sys/ioctl.h>
- #include <features.h>
- #include <linux/hdreg.h>
- #include <sys/mount.h> /* BLKFLSBUF */
- #else
- #include <sys/ioctl.h>
- #include <sys/disklabel.h>
- #include <sys/disk.h>
- #endif
- #include "types.h"
- #include "common.h"
- #include "fnctdsk.h"
- #include "hdaccess.h"
- #include "readpart.h"
- #ifndef O_BINARY
- #define O_BINARY 0
- #endif
-
- struct info_file
- {
- int handle;
- unsigned int offset;
- char name[DISKNAME_MAX];
- };
-
- static char *file_description(t_param_disk *disk_car);
- static int file_clean(t_param_disk *disk_car);
- static int file_read(t_param_disk *disk_car, const unsigned int nbr_sector, void *nom_buffer, const dword pos);
- static int file_write(t_param_disk *disk_car, const unsigned int nbr_sector, const void *nom_buffer, const dword pos);
- static int file_nowrite(t_param_disk *disk_car, const unsigned int nbr_sector, const void *nom_buffer, const dword pos);
-
- #ifdef DJGPP
- #define HD_RW_BUF_SIZ 0x10
- #define HDPARM_BUF_SIZ 0x1A
- #define MAX_IO_NBR 3
- #define MAX_HD_ERR 100
- #define PARA_CMD 8
- static int hd_super(int cmd, t_param_disk *disk_car, dword hd_offset, int nsects, void *buffer);
- static t_param_disk *hd_identify(const int debug, const unsigned int disk);
- static int hd_identify_enh_bios(t_param_disk *param_disk,const int debug);
- static int check_enh_bios(const unsigned int disk, const int debug);
- static int hd_report_error(t_param_disk *disk_car, const dword hd_offset, const unsigned int nbr_sector, const int rc);
- static char *disk_description(t_param_disk *disk_car);
- static int disk_read(t_param_disk *disk_car, const unsigned int nbr_sector, void *nom_buffer, const dword hd_offset);
- static int disk_write(t_param_disk *disk_car, const unsigned int nbr_sector, const void *nom_buffer, const dword hd_offset);
- struct info_disk
- {
- unsigned int disk;
- t_CHS CHSR; /* CHS low level */
- int mode;
- unsigned int nbr_err;
- int bad_geometry;
- };
-
- static int dos_segment = 0;
- static int dos_selector = 0;
-
- void free_dos_buffer(void)
- {
- __dpmi_free_dos_memory(dos_selector);
- dos_segment = dos_selector = 0;
- }
-
- int alloc_dos_buffer(void)
- {
- if (dos_segment)
- return 0;
- if ((dos_segment = __dpmi_allocate_dos_memory(18*SECTOR_SIZE/16, &dos_selector))== -1)
- {
- dos_segment = 0;
- return 1;
- }
- atexit(free_dos_buffer);
- return 0;
- }
-
- static int hd_super(int cmd, t_param_disk *disk_car, dword hd_offset, int nsects, void *buffer)
- {
- __dpmi_regs r;
- unsigned char buf[HD_RW_BUF_SIZ];
- int dos_segment2, dos_selector2, xfer2=nsects*SECTOR_SIZE;
- struct info_disk*data=disk_car->data;
-
- if((data->mode==0)||(cmd==0))
- { /* Limite CHS = 1023,255,63 = 8,064Mo ~= 7.8 Go */
- int head, track, sector;
- sector=(hd_offset%data->CHSR.sector)+1;
- hd_offset/=data->CHSR.sector;
- head=hd_offset%(data->CHSR.head+1);
- track=hd_offset/(data->CHSR.head+1);
- if(track<1024)
- return biosdisk(cmd, data->disk, head, track, sector, nsects, buffer);
- return 1;
- }
- if(dos_segment==0)
- if(alloc_dos_buffer())
- return 1;
- if ( (dos_segment2=__dpmi_allocate_dos_memory((xfer2 + 15) >> 4, &dos_selector2)) == -1 )
- return 1;
- *(word*)&buf[0]=HD_RW_BUF_SIZ;
- *(word*)&buf[2]=nsects;
- *(dword*)&buf[0x4]=dos_segment2<<16;
- *(dword*)&buf[0x8]=hd_offset;
- *(dword*)&buf[0xC]=0;
-
- r.x.ds = dos_segment;
- r.x.si = 0;
- r.h.dl = data->disk;
- switch(cmd)
- {
- case 2:
- r.h.ah = 0x42;
- break;
- case 3:
- r.x.ax = 0x4300;
- dosmemput(buffer,xfer2,dos_segment2<<4);
- break;
- case 0x0C:
- r.h.ah = 0x47;
- break;
- }
- dosmemput(&buf, HD_RW_BUF_SIZ, dos_segment<<4);
- __dpmi_int(0x13, &r);
- if(cmd==2)
- dosmemget(dos_segment2<<4, xfer2, buffer);
- __dpmi_free_dos_memory(dos_selector2);
- #ifdef DEBUG
- if(r.h.ah)
- {
- wdoprintf(stdscr," %lu err %02X %04X\n",*(dword*)&buf[0x8], r.h.ah,r.x.flags);
- }
- #endif
- return r.h.ah;
- }
-
- static int check_enh_bios(const unsigned int disk, const int debug)
- {
- __dpmi_regs r;
- r.h.ah = 0x41;
- r.x.bx = 0x55AA;
- r.h.dl = disk;
- __dpmi_int(0x13, &r);
- if(r.x.bx != 0xAA55) /* INT 13 Extensions not installed */
- {
- if(debug)
- ecrit_rapport("Disk %02X - INT 13 Extensions not installed\n",disk);
- return 0;
- }
- if(debug)
- {
- ecrit_rapport("Disk %02X ",disk);
- switch(r.h.ah)
- {
- case 0x01:
- ecrit_rapport("Enhanced BIOS 1.x");
- break;
- case 0x20:
- ecrit_rapport("Enhanced BIOS 2.0 / EDD-1.0");
- break;
- case 0x21:
- ecrit_rapport("Enhanced BIOS 2.1 / EDD-1.1");
- break;
- case 0x30:
- ecrit_rapport("Enhanced BIOS EDD-3.0");
- break;
- default:
- ecrit_rapport("Enhanced BIOS unknown %02X",r.h.ah);
- break;
- }
- if((r.x.cx & 1)!=0)
- ecrit_rapport(" - R/W/I");
- if((r.x.cx & 4)!=0)
- ecrit_rapport(" - Identify");
- ecrit_rapport("\n");
- }
- return ((r.x.cx&1)!=0);
- }
-
- static int hd_identify_enh_bios(t_param_disk *disk_car,const int debug)
- {
- int compute_LBA=0;
- __dpmi_regs r;
- unsigned char buf[0x200]; /* Don't change it! */
- struct info_disk*data=disk_car->data;
- buf[0]=HDPARM_BUF_SIZ;
- buf[1]=0;
- if(dos_segment==0)
- if(alloc_dos_buffer())
- return 1;
- r.h.ah = 0x48;
- r.x.ds = dos_segment;
- r.x.si = 0;
- r.h.dl = data->disk;
- dosmemput(&buf, HDPARM_BUF_SIZ, dos_segment<<4);
- __dpmi_int(0x13, &r);
- dosmemget(dos_segment<<4, HDPARM_BUF_SIZ, &buf);
- if(r.h.ah)
- return 1;
- disk_car->CHS.cylinder=*(word*)&buf[0x04];
- disk_car->CHS.head=*(word*)&buf[0x08];
- disk_car->CHS.sector=*(word*)&buf[0x0C];
- disk_car->size=(*(dword*)&buf[0x10]);
- if(disk_car->size==0)
- {
- disk_car->CHS.cylinder--;
- disk_car->CHS.head--;
- compute_LBA=1;
- disk_car->size=(disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector;
- if(debug)
- ecrit_rapport("Computes LBA from CHS\n");
- }
- else
- {
- if(disk_car->CHS.cylinder>0 && disk_car->CHS.head>0 && disk_car->CHS.sector>0)
- {
- disk_car->CHS.cylinder--;
- disk_car->CHS.head--;
- /* Some bios are buggy */
- if(disk_car->size>(disk_car->CHS.cylinder+2)*(disk_car->CHS.head+1)*disk_car->CHS.sector)
- {
- disk_car->CHS.cylinder=(disk_car->size/(disk_car->CHS.head+1))/disk_car->CHS.sector-1;
- if(debug)
- ecrit_rapport("Computes C from number of sectors\n");
- }
- }
- else
- {
- if(debug)
- ecrit_rapport("Computes CHS from number of sectors\n");
- disk_car->CHS.head=255-1;
- disk_car->CHS.sector=63;
- disk_car->CHS.cylinder=(disk_car->size/(disk_car->CHS.head+1))/disk_car->CHS.sector-1;
- }
- }
- if(disk_car->CHS.sector==0)
- {
- data->bad_geometry=1;
- disk_car->CHS.sector=1;
- ecrit_rapport("Incorrect number of sector\n");
- }
- if(disk_car->CHS.sector>63)
- {
- data->bad_geometry=1;
- ecrit_rapport("Incorrect number of sector\n");
- }
- if(disk_car->CHS.head>255-1)
- {
- data->bad_geometry=1;
- ecrit_rapport("Incorrect number of head\n");
- }
- if(debug || data->bad_geometry)
- ecrit_rapport("LBA %lu, computed %u (CHS=%u,%u,%u)\n",disk_car->size, (disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector,disk_car->CHS.cylinder,disk_car->CHS.head,disk_car->CHS.sector);
- if(compute_LBA)
- disk_car->size=(disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector;
- else
- {
- if(disk_car->size < (disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector)
- {
- ecrit_rapport("Computes LBA from CHS, previous value may be false.\n");
- disk_car->size=(disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector;
- }
- }
- data->CHSR.cylinder=disk_car->CHS.cylinder;
- data->CHSR.head=disk_car->CHS.head;
- data->CHSR.sector=disk_car->CHS.sector;
- if(debug)
- {
- ecrit_rapport("hd_identify_enh_bios\n");
- ecrit_rapport("%s",disk_description(disk_car));
- ecrit_rapport("LBA size=%lu\n",disk_car->size);
- }
- return 0;
- }
-
- static t_param_disk *hd_identify(const int debug, const unsigned int disk)
- {
- unsigned char buf[0x200];
- memset(buf,0,sizeof(buf));
- /* standard BIOS access */
- if(biosdisk(PARA_CMD,disk,0,0,1,1,buf))
- return NULL;
- if(debug>1)
- ecrit_rapport("Disk %02X %u max %02X\n",disk,buf[2],(0x80+buf[2]-1));
- if(disk>(unsigned int)(0x80+buf[2]-1))
- return NULL;
- {
- struct info_disk*data=(struct info_disk*)MALLOC(sizeof(*data));
- t_param_disk *disk_car=(t_param_disk *)MALLOC(sizeof(*disk_car));
- data->disk=disk;
- data->bad_geometry=0;
- data->mode=0;
- data->nbr_err=0;
- disk_car->halt_on_errors=0;
- disk_car->write_used=0;
- disk_car->description=disk_description;
- disk_car->read=disk_read;
- disk_car->write=disk_write;
- disk_car->clean=file_clean;
- disk_car->data=data;
- disk_car->CHS.cylinder=((buf[0] & 0x0C0)<<2)|buf[1];
- disk_car->CHS.head=buf[3];
- disk_car->CHS.sector=buf[0] & 0x3F;
- if(disk_car->CHS.head>=255)
- { /* Problem found by G Rowe */
- ecrit_rapport("BIOS reports an invalid heads number\n");
- data->bad_geometry=1;
- disk_car->CHS.head=254;
- }
- if(disk_car->CHS.sector==0)
- { /* Problem found by Brian Barrett */
- ecrit_rapport("BIOS reports an invalid number of sector per head\n");
- data->bad_geometry=1;
- disk_car->CHS.sector=1;
- }
- disk_car->size=(disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector;
- data->CHSR.cylinder=disk_car->CHS.cylinder;
- data->CHSR.head=disk_car->CHS.head;
- data->CHSR.sector=disk_car->CHS.sector;
- if(debug)
- ecrit_rapport("%s",disk_description(disk_car));
- if(check_enh_bios(disk,debug))
- {
- /* enhanced BIOS access */
- t_param_disk *param_disk_enh=(t_param_disk*)MALLOC(sizeof(*param_disk_enh));
- param_disk_enh->halt_on_errors=0;
- param_disk_enh->write_used=0;
- param_disk_enh->data=data;
- data->mode=1;
- if(!hd_identify_enh_bios(param_disk_enh,debug))
- {
- /* standard geometry H,S, compute C from LBA */
- disk_car->size=param_disk_enh->size;
- disk_car->CHS.cylinder=(disk_car->size/(disk_car->CHS.head+1))/disk_car->CHS.sector-1;
- }
- else
- data->mode=0;
- FREE(param_disk_enh);
- }
- return disk_car;
- }
- }
-
- static char *disk_description(t_param_disk *disk_car)
- {
- struct info_disk*data=disk_car->data;
- sprintf(disk_car->description_txt, "Disk %2x - CHS %u %u %u - %u MB %s\n",
- data->disk, disk_car->CHS.cylinder+1, disk_car->CHS.head+1, disk_car->CHS.sector,(disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector/2/1024,data->bad_geometry?" (Buggy BIOS)":"");
- return disk_car->description_txt;
- }
-
- static int disk_read(t_param_disk *disk_car,const unsigned int nbr_sector, void *nom_buffer, const dword hd_offset)
- {
- struct info_disk*data=disk_car->data;
- /* CHS=(0,1,1) */
- if(hd_offset==disk_car->CHS.sector)
- {
- data->nbr_err=0;
- }
- if((data->nbr_err>MAX_HD_ERR)&&disk_car->halt_on_errors)
- {
- if(data->nbr_err==(MAX_HD_ERR+1))
- {
- ecrit_rapport("\ndata->nbr_err>MAX_HD_ERR !!!\n");
- data->nbr_err++;
- }
- return 1;
- }
- if((data->CHSR.cylinder==0) || (hd_offset+nbr_sector-1<=disk_car->size))
- {
- int rc=0;
- unsigned int offset=0;
- unsigned int read_size;
- for(offset=0;(rc==0) && (offset<nbr_sector);offset+=read_size)
- {
- int i;
- read_size=nbr_sector-offset>16?16:nbr_sector-offset;
- rc=4; /* sector not found/read error */
- for(i=0;(rc!=0) && (rc!=1) && (i<MAX_IO_NBR);i++)
- {
- rc=hd_super(2, disk_car, hd_offset+offset, read_size, (char*)nom_buffer+offset*SECTOR_SIZE);
- if(rc!=0)
- {
- hd_super(0, disk_car, 0, 1, NULL);
- }
- }
- }
- if(rc!=0)
- {
- ecrit_rapport("disk_read");
- hd_report_error(disk_car,hd_offset,nbr_sector,rc);
- }
- return rc;
- }
- return 1;
- }
-
- static int disk_write(t_param_disk *disk_car,const unsigned int nbr_sector, const void *nom_buffer, const dword hd_offset)
- {
- struct info_disk*data=disk_car->data;
- disk_car->write_used=1;
- if((data->nbr_err>MAX_HD_ERR)&&disk_car->halt_on_errors)
- {
- if(data->nbr_err==(MAX_HD_ERR+1))
- {
- ecrit_rapport("\ndata->nbr_err>MAX_HD_ERR !!!\n");
- data->nbr_err++;
- }
- return 1;
- }
- {
- int i,rc=4; /* sector not found/read error */
- for(i=0;(rc==4)&&(i<MAX_IO_NBR);i++)
- {
- rc=hd_super(3, disk_car, hd_offset, nbr_sector, nom_buffer);
- }
- if(rc)
- {
- ecrit_rapport("disk_write");
- hd_report_error(disk_car,hd_offset,nbr_sector,rc);
- }
- return rc;
- }
- }
-
- static int hd_report_error(t_param_disk *disk_car, const dword hd_offset, const unsigned int nbr_sector, const int rc)
- {
- struct info_disk*data=disk_car->data;
- data->nbr_err++;
- ecrit_rapport(" lba=%lu(%u/%u/%u) nbr_sector=%u, rc=%d\n",hd_offset,
- LBA2cylinder(disk_car,hd_offset),LBA2head(disk_car,hd_offset),LBA2sector(disk_car,hd_offset),
- nbr_sector,rc);
- switch(rc)
- {
- case 0x00: ecrit_rapport("successful completion"); break;
- case 0x01: ecrit_rapport("invalid function in AH or invalid parameter"); break;
- case 0x02: ecrit_rapport("address mark not found"); break;
- case 0x03: ecrit_rapport("disk write-protected"); break;
- case 0x04: ecrit_rapport("sector not found/read error"); break;
- case 0x05: ecrit_rapport("reset failed (hard disk)"); break;
- case 0x06: ecrit_rapport("disk changed (floppy)"); break;
- case 0x07: ecrit_rapport("drive parameter activity failed (hard disk)"); break;
- case 0x08: ecrit_rapport("DMA overrun"); break;
- case 0x09: ecrit_rapport("data boundary error (attempted DMA across 64K boundary or >80h sectors)"); break;
- case 0x0A: ecrit_rapport("bad sector detected (hard disk)"); break;
- case 0x0B: ecrit_rapport("bad track detected (hard disk)"); break;
- case 0x0C: ecrit_rapport("unsupported track or invalid media"); break;
- case 0x0D: ecrit_rapport("invalid number of sectors on format (PS/2 hard disk)"); break;
- case 0x0E: ecrit_rapport("control data address mark detected (hard disk)"); break;
- case 0x0F: ecrit_rapport("DMA arbitration level out of range (hard disk)"); break;
- case 0x10: ecrit_rapport("uncorrectable CRC or ECC error on read"); break;
- case 0x11: ecrit_rapport("data ECC corrected (hard disk)"); break;
- case 0x20: ecrit_rapport("controller failure"); break;
- case 0x31: ecrit_rapport("no media in drive (IBM/MS INT 13 extensions)"); break;
- case 0x32: ecrit_rapport("incorrect drive type stored in CMOS (Compaq)"); break;
- case 0x40: ecrit_rapport("seek failed"); break;
- case 0x80: ecrit_rapport("timeout (not ready)"); break;
- case 0xAA: ecrit_rapport("drive not ready (hard disk)"); break;
- case 0xB0: ecrit_rapport("volume not locked in drive (INT 13 extensions)"); break;
- case 0xB1: ecrit_rapport("volume locked in drive (INT 13 extensions)"); break;
- case 0xB2: ecrit_rapport("volume not removable (INT 13 extensions)"); break;
- case 0xB3: ecrit_rapport("volume in use (INT 13 extensions)"); break;
- case 0xB4: ecrit_rapport("lock count exceeded (INT 13 extensions)"); break;
- case 0xB5: ecrit_rapport("valid eject request failed (INT 13 extensions)"); break;
- case 0xB6: ecrit_rapport("volume present but read protected (INT 13 extensions)"); break;
- case 0xBB: ecrit_rapport("undefined error (hard disk)"); break;
- case 0xCC: ecrit_rapport("write fault (hard disk)"); break;
- case 0xE0: ecrit_rapport("status register error (hard disk)"); break;
- case 0xFF: ecrit_rapport("sense operation failed (hard disk)"); break;
- }
- ecrit_rapport("\n");
- return 0;
- }
-
- t_list_disk *hd_parse(t_list_disk *list_disk,const int debug)
- {
- int i;
- int ind_stop=0;
- for(i=0x80;(i<0x88)&&!ind_stop;i++)
- {
- t_param_disk *disk_car=hd_identify(debug,i);
- if(disk_car)
- list_disk=insert_new_disk(list_disk,disk_car);
- else
- ind_stop=1;
- }
- /* hdimage */
- {
- t_param_disk *disk_car=file_test_availability( "hdimage",debug);
- if(disk_car)
- list_disk=insert_new_disk(list_disk,disk_car);
- }
- return list_disk;
- }
- #elif defined(LINUX)
- static t_param_disk *disk_get_geometry(const int hd_h, const char *device, const int debug);
-
- static t_param_disk *disk_get_geometry(const int hd_h, const char *device, const int debug)
- {
- t_param_disk *disk_car=NULL;
- /* Little trick from Linux fdisk */
- /* Blocks are visible in more than one way:
- e.g. as block on /dev/hda and as block on /dev/hda3
- By a bug in the Linux buffer cache, we will see the old
- contents of /dev/hda when the change was made to /dev/hda3.
- In order to avoid this, discard all blocks on /dev/hda. */
- ioctl(hd_h, BLKFLSBUF); /* ignore errors */
- /* e.g. Permission Denied */
- #ifdef HDIO_GETGEO_BIG
- {
- struct hd_big_geometry geometry_big;
- if (ioctl(hd_h, HDIO_GETGEO_BIG, &geometry_big)==0)
- { /* I can get the geometry */
- if(debug>1)
- {
- ecrit_rapport("disk_get_geometry %s HDIO_GETGEO_BIG Ok\n",device);
- }
- disk_car=(t_param_disk *)MALLOC(sizeof(*disk_car));
- disk_car->CHS.cylinder= geometry_big.cylinders-1;
- disk_car->CHS.head=geometry_big.heads-1;
- disk_car->CHS.sector= geometry_big.sectors;
- }
- else
- {
- if(debug>1)
- {
- ecrit_rapport("disk_get_geometry %s: HDIO_GETGEO_BIG failed\n",device);
- }
- }
- }
- #endif
- if (disk_car==NULL)
- {
- struct hd_geometry geometry;
- if(ioctl(hd_h, HDIO_GETGEO, &geometry)==0)
- { /* I can get the geometry */
- if(debug>1)
- {
- ecrit_rapport("disk_get_geometry %s HDIO_GETGEO Ok\n",device);
- }
- disk_car=(t_param_disk *)MALLOC(sizeof(*disk_car));
- disk_car->CHS.cylinder= geometry.cylinders-1;
- disk_car->CHS.head=geometry.heads-1;
- disk_car->CHS.sector= geometry.sectors;
- }
- }
- return disk_car;
- }
-
- t_list_disk *hd_parse(t_list_disk *list_disk,const int debug)
- {
- int i,j;
- char device_ide[]="/dev/hda";
- char device_scsi[]="/dev/sda";
- char device_ida[]="/dev/ida/c0d0";
- char device_cciss[]="/dev/cciss/c0d0";
- char device_rd[]="/dev/rd/c0d0";
- char device_rd_ide[]="/dev/ataraid/d0";
- char device_p_ide[]="/dev/pda";
- char device_i2o_hd[]="/dev/i2o/hda";
- /* Disk IDE */
- for(i=0;i<8;i++)
- {
- device_ide[strlen(device_ide)-1]='a'+i;
- list_disk=insert_new_disk(list_disk,file_test_availability(device_ide,debug));
- }
- /* Disk SCSI */
- for(i=0;i<26;i++)
- {
- device_scsi[strlen(device_scsi)-1]='a'+i;
- list_disk=insert_new_disk(list_disk,file_test_availability(device_scsi,debug));
- }
- /* Device RAID Compaq */
- for(j=0;j<8;j++)
- {
- device_ida[strlen(device_ida)-3]='0'+j;
- for(i=0;i<8;i++)
- {
- device_ida[strlen(device_ida)-1]='0'+i;
- list_disk=insert_new_disk(list_disk,file_test_availability(device_ida,debug));
- }
- }
- for(i=0;i<8;i++)
- {
- device_cciss[strlen(device_cciss)-1]='0'+i;
- list_disk=insert_new_disk(list_disk,file_test_availability(device_cciss,debug));
- }
- /* Device RAID */
- for(i=0;i<10;i++)
- {
- device_rd[strlen(device_rd)-1]='0'+i;
- list_disk=insert_new_disk(list_disk,file_test_availability(device_rd,debug));
- }
- /* Device RAID IDE */
- for(i=0;i<15;i++)
- {
- device_rd_ide[strlen(device_rd_ide)-1]='0'+i;
- list_disk=insert_new_disk(list_disk,file_test_availability(device_rd_ide,debug));
- }
- /* Parallel port IDE disk */
- for(i=0;i<4;i++)
- {
- device_p_ide[strlen(device_p_ide)-1]='a'+i;
- list_disk=insert_new_disk(list_disk,file_test_availability(device_p_ide,debug));
- }
- /* I2O hard disk */
- for(i=0;i<26;i++)
- {
- device_i2o_hd[strlen(device_i2o_hd)-1]='a'+i;
- list_disk=insert_new_disk(list_disk,file_test_availability(device_i2o_hd,debug));
- }
- /* hdimage */
- list_disk=insert_new_disk(list_disk,file_test_availability("hdimage",debug));
- #ifdef TEST
- {
- t_list_disk *disk;
- for(disk=list_disk;disk;disk=disk->next)
- {
- disk->disk=new_diskcache(disk->disk);
- }
- }
- #endif
- return list_disk;
- }
- #else
- static t_param_disk *disk_get_geometry(const int hd_h, const char *device, const int debug);
-
- static t_param_disk *disk_get_geometry(const int hd_h, const char *device, const int debug)
- {
- t_param_disk *disk_car=NULL;
- struct disklabel geometry;
- if (ioctl(hd_h, DIOCGDINFO, &geometry)==0)
- { /* I can get the geometry */
- if(debug>1)
- {
- ecrit_rapport("disk_get_geometry %s: Ok\n",device);
- }
- disk_car=(t_param_disk *)MALLOC(sizeof(*disk_car));
- disk_car->CHS.cylinder=geometry.d_ncylinders-1;
- disk_car->CHS.head=geometry.d_ntracks-1;
- disk_car->CHS.sector=geometry.d_nsectors;
- }
- else
- {
- int error;
- u_int u,sectors,heads,cyls;
- off_t o;
- if(debug>1)
- {
- ecrit_rapport("disk_get_geometry %s: DIOCGDINFO failed %s\n",device,strerror(errno));
- }
- error = ioctl(hd_h, DIOCGFWSECTORS, &u);
- if(error==0 && u>0)
- {
- sectors=u;
- }
- else
- {
- sectors=63;
- if(debug>1)
- {
- ecrit_rapport("disk_get_geometry %s: DIOCGFWSECTORS failed %s\n",device,strerror(errno));
- }
- }
- error = ioctl(hd_h, DIOCGFWHEADS, &u);
- if(error==0 && u>0)
- {
- heads=u;
- }
- else
- {
- heads=255;
- if(debug>1)
- {
- ecrit_rapport("disk_get_geometry %s: DIOCGFWHEADS failed %s\n",device,strerror(errno));
- }
- }
- error = ioctl(hd_h, DIOCGMEDIASIZE, &o);
- if(error==0)
- {
- cyls = o / (512 * heads * sectors);
- disk_car=(t_param_disk *)MALLOC(sizeof(*disk_car));
- disk_car->CHS.cylinder=cyls-1;
- disk_car->CHS.head=heads-1;
- disk_car->CHS.sector=sectors;
- }
- else
- {
- if(debug>1)
- {
- ecrit_rapport("disk_get_geometry %s: DIOCGMEDIASIZE failed %s\n",device,strerror(errno));
- }
- }
- }
- return disk_car;
- }
-
- t_list_disk *hd_parse(t_list_disk *list_disk,const int debug)
- {
- /* Need to check http://mattriffle.com/mirrors/freebsd/doc/en_US.ISO8859-1/books/handbook/disks-naming.html#DISK-NAMING-PHYSICAL-TABLE */
- int i;
- char device_ide[]= "/dev/rwd0"; /* raw winchester disk */
- char device_ide2[]="/dev/rad0";
- char device_scsi[]="/dev/rda0"; /* raw scsci disk */
- char device_optdisk[]="/dev/rod0";
- char device_ide_hd[]="/dev/ad0";
- char device_scsi_hd[]="/dev/da0";
- /* wd da */
- /* Disk IDE */
- for(i=0;i<8;i++)
- {
- device_ide[strlen(device_ide)-1]='0'+i;
- list_disk=insert_new_disk(list_disk,file_test_availability(device_ide,debug));
- }
- for(i=0;i<8;i++)
- {
- device_ide2[strlen(device_ide2)-1]='0'+i;
- list_disk=insert_new_disk(list_disk,file_test_availability(device_ide2,debug));
- }
- for(i=0;i<8;i++)
- {
- device_ide_hd[strlen(device_ide_hd)-1]='0'+i;
- list_disk=insert_new_disk(list_disk,file_test_availability(device_ide_hd,debug));
- }
- /* Disk SCSI */
- for(i=0;i<8;i++)
- {
- device_scsi[strlen(device_scsi)-1]='0'+i;
- list_disk=insert_new_disk(list_disk,file_test_availability(device_scsi,debug));
- }
- for(i=0;i<8;i++)
- {
- device_scsi_hd[strlen(device_scsi_hd)-1]='0'+i;
- list_disk=insert_new_disk(list_disk,file_test_availability(device_scsi_hd,debug));
- }
- /* optical disks */
- for(i=0;i<8;i++)
- {
- device_optdisk[strlen(device_scsi)-1]='a'+i;
- list_disk=insert_new_disk(list_disk,file_test_availability(device_optdisk,debug));
- }
- /* */
-
- /* hdimage */
- list_disk=insert_new_disk(list_disk,file_test_availability("hdimage",debug));
- return list_disk;
- }
- #endif
-
- static char *file_description(t_param_disk *disk_car)
- {
- struct info_file *data=disk_car->data;
- snprintf(disk_car->description_txt, sizeof(disk_car->description_txt),"Disk %s - CHS %u %u %u - %u MB\n",
- data->name, disk_car->CHS.cylinder+1, disk_car->CHS.head+1, disk_car->CHS.sector,(disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector/2/1024);
- return disk_car->description_txt;
- }
-
- static int file_clean(t_param_disk *disk_car)
- {
- if(disk_car->data!=NULL)
- {
- FREE(disk_car->data);
- disk_car->data=NULL;
- }
- return 0;
- }
-
- static int file_read(t_param_disk *disk_car,const unsigned int nbr_sector, void *nom_buffer, dword pos)
- {
- struct info_file *data=disk_car->data;
- long int ret;
- /* ecrit_rapport("file_read(%d,%u,buffer,%lu(%u/%u/%u))\n", data->handle,nbr_sector,pos, */
- /* LBA2cylinder(disk_car,pos),LBA2head(disk_car,pos),LBA2sector(disk_car,pos)); */
- #ifdef TESTING
- if(rand()%10==0) /* TEST ONLY ICI */
- {
- /* ecrit_rapport("file_read(%u,%u,buffer,%lu) seek err\n", data->handle,nbr_sector,pos); */
- return -1;
- }
- if(LBA2cylinder(disk_car,pos)>1 && LBA2cylinder(disk_car,pos)<600)
- {
- memset(nom_buffer,0,nbr_sector*SECTOR_SIZE);
- return 0;
- }
- #endif
- if(lseek(data->handle,((loff_t)pos<<9)+(loff_t)data->offset,SEEK_SET)==-1)
- {
- ecrit_rapport("file_read(%d,%u,buffer,%lu(%u/%u/%u)) seek err %s\n", data->handle,nbr_sector,pos,
- LBA2cylinder(disk_car,pos),LBA2head(disk_car,pos),LBA2sector(disk_car,pos),strerror(errno));
- return -1;
- }
- ret=read(data->handle, nom_buffer, nbr_sector*SECTOR_SIZE);
- if(ret!=(long int)(nbr_sector*SECTOR_SIZE))
- {
- ecrit_rapport("file_read(%d,%u,buffer,%lu(%u/%u/%u)) read err %s (ret!=nbr_sector*SECTOR_SIZE)\n", data->handle,nbr_sector,pos,
- LBA2cylinder(disk_car,pos),LBA2head(disk_car,pos),LBA2sector(disk_car,pos),(ret==-1?strerror(errno):"Truncated file"));
- return -1;
- }
- return 0;
- }
-
- static int file_write(t_param_disk *disk_car,const unsigned int nbr_sector, const void *nom_buffer, const dword pos)
- {
- long int ret;
- struct info_file *data=disk_car->data;
- if(lseek(data->handle,((loff_t)pos<<9)+(loff_t)(data->offset),SEEK_SET)==-1)
- {
- ecrit_rapport("file_write(%d,%u,buffer,%lu(%u/%u/%u)) seek err %s\n", data->handle,nbr_sector,pos,
- LBA2cylinder(disk_car,pos),LBA2head(disk_car,pos),LBA2sector(disk_car,pos),strerror(errno));
- return -1;
- }
- disk_car->write_used=1;
- ret=write(data->handle, nom_buffer, nbr_sector*SECTOR_SIZE);
- if(ret!=(long int)nbr_sector*SECTOR_SIZE)
- {
- ecrit_rapport("file_write(%d,%u,buffer,%lu(%u/%u/%u)) write err %s\n", data->handle,nbr_sector,pos,
- LBA2cylinder(disk_car,pos),LBA2head(disk_car,pos),LBA2sector(disk_car,pos),(ret==-1?strerror(errno):"File truncated"));
- return -1;
- }
- return 0;
- }
-
- static int file_nowrite(t_param_disk *disk_car,const unsigned int nbr_sector, const void *nom_buffer, const dword pos)
- {
- struct info_file *data=disk_car->data;
- ecrit_rapport("write_file(%d,%u,buffer,%lu(%u/%u/%u)) write refused\n", data->handle,nbr_sector,pos,
- LBA2cylinder(disk_car,pos),LBA2head(disk_car,pos),LBA2sector(disk_car,pos));
- return -1;
- }
-
- t_param_disk *file_test_availability(const char *device, const int debug)
- {
- unsigned int offset=0;
- t_param_disk *disk_car=NULL;
- int hd_h;
- int no_write=0;
- #ifdef O_LARGEFILE
- hd_h = open(device, O_RDWR|O_LARGEFILE|O_BINARY);
- #else
- hd_h = open(device, O_RDWR|O_BINARY);
- #endif
- if(hd_h<0)
- {
- if(debug>1)
- {
- ecrit_rapport("file_test_availability %s:%s\n", device,strerror(errno));
- }
- /* if(errno==EROFS||errno==EACCES|errno==EPERM) */
- {
- no_write=1;
- #ifdef O_LARGEFILE
- hd_h = open(device, O_RDONLY|O_LARGEFILE|O_BINARY);
- #else
- hd_h = open(device, O_RDONLY|O_BINARY);
- #endif
- if(hd_h<0)
- {
- if(debug>1)
- {
- ecrit_rapport("file_test_availability %s:%s\n", device,strerror(errno));
- }
- }
- }
- }
- if(hd_h>0)
- {
- struct stat stat_rec;
- if(fstat(hd_h,&stat_rec)<0)
- {
- if(debug>1)
- {
- ecrit_rapport("file_test_availability %s: fstat failed\n",device);
- }
- close(hd_h);
- return NULL;
- }
- if(!S_ISREG(stat_rec.st_mode))
- {
- if(debug>1)
- {
- ecrit_rapport("file_test_availability %s: not a regular file\n",device);
- }
- #ifndef DJGPP
- disk_car=disk_get_geometry(hd_h, device, debug);
- if(disk_car!=NULL)
- {
- disk_car->size=(disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector;
- }
- #endif
- }
- else
- {
- unsigned char buffer[SECTOR_SIZE];
- if(read(hd_h,buffer,sizeof(buffer))!=sizeof(buffer))
- {
- close(hd_h);
- return NULL;
- }
- if(memcmp(buffer,"DOSEMU",6)==0)
- {
- if(*(unsigned long*)(buffer+11)==0)
- {
- ecrit_rapport("%s corrupted DOSEMU file\n",device);
- close(hd_h);
- return NULL;
- }
- if(debug)
- {
- ecrit_rapport("%s DOSEMU\n",device);
- }
- disk_car=(t_param_disk *)MALLOC(sizeof(*disk_car));
- disk_car->CHS.head=*(unsigned long*)(buffer+7)-1;
- disk_car->CHS.sector=*(unsigned long*)(buffer+11);
- disk_car->CHS.cylinder=*(unsigned long*)(buffer+15)-1;
- disk_car->size=(disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector;
- offset=*(unsigned long*)(buffer+19);
- }
- else
- {
- t_CHS geometry;
- disk_car=(t_param_disk *)MALLOC(sizeof(*disk_car));
- disk_car->size=(stat_rec.st_size-offset)/SECTOR_SIZE;
- get_geometry_from_mbr(buffer, debug, &geometry);
- if(geometry.sector>0)
- {
- disk_car->CHS.head=geometry.head;
- disk_car->CHS.sector=geometry.sector;
- }
- else
- {
- disk_car->CHS.head=255-1;
- disk_car->CHS.sector=63;
- }
- /* Round up because file is often truncated. */
- disk_car->CHS.cylinder=(disk_car->size+disk_car->CHS.sector*(disk_car->CHS.head+1)-1)/disk_car->CHS.sector/(disk_car->CHS.head+1)-1;
- }
- }
- if(disk_car!=NULL)
- {
- struct info_file *data=MALLOC(sizeof(*data));
- data->offset=offset;
- strncpy(data->name,device,sizeof(data->name));
- data->handle=hd_h;
- disk_car->halt_on_errors=0;
- disk_car->write_used=0;
- disk_car->description=file_description;
- disk_car->read=file_read;
- disk_car->write=(no_write==0?file_write:file_nowrite);
- disk_car->clean=file_clean;
- disk_car->data=data;
- return disk_car;
- }
- else
- {
- close(hd_h);
- }
- }
- return NULL;
- }
-
- void hd_parse_bis(const t_list_disk * list_disk, const int allow_partial_last_cylinder)
- {
- const t_list_disk *element_disk;
- for(element_disk=list_disk;element_disk;element_disk=element_disk->next)
- {
- t_param_disk *disk_car=element_disk->disk;
- char buffer[SECTOR_SIZE];
- dword pos;
- t_CHS pos_CHS;
- dup_t_CHS(&pos_CHS,&disk_car->CHS);
- pos_CHS.cylinder++;
- if(allow_partial_last_cylinder) {
- pos_CHS.head=0;
- pos_CHS.sector=1;
- }
- pos=CHS2LBA(disk_car,&pos_CHS);
- #ifdef DJGPP
- if(disk_car->description==disk_description)
- {
- struct info_disk*data=disk_car->data;
- data->CHSR.cylinder=0;
- }
- #endif
- if(disk_car->read(element_disk->disk,1, &buffer, pos)==0)
- {
- disk_car->CHS.cylinder++;
- if(disk_car->size < (disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector)
- {
- disk_car->size=(disk_car->CHS.cylinder+1)*(disk_car->CHS.head+1)*disk_car->CHS.sector;
- ecrit_rapport("Computes LBA from CHS for %s\n",disk_car->description(disk_car));
- }
- }
- #ifdef DJGPP
- if(disk_car->description==disk_description)
- {
- struct info_disk*data=disk_car->data;
- data->CHSR.cylinder=disk_car->CHS.cylinder;
- }
- #endif
- }
- }
-
- #ifdef TEST
- struct info_cache
- {
- t_param_disk *disk_car;
- unsigned int nbr_read;
- unsigned int nbr_write;
- };
-
- static int cache_read(t_param_disk *disk_car,const unsigned int nbr_sector, void *nom_buffer, const dword pos);
- static int cache_write(t_param_disk *disk_car,const unsigned int nbr_sector, const void *nom_buffer, const dword pos);
- static int cache_clean(t_param_disk *clean);
-
- static int cache_read(t_param_disk *disk_car,const unsigned int nbr_sector, void *nom_buffer, const dword pos)
- {
- static char buffer[8*SECTOR_SIZE];
- static dword old_pos=1234;
- int res=0;
- struct info_cache *data=disk_car->data;
- ecrit_rapport("cache_read(%u,buffer,%lu(%u/%u/%u))\n", nbr_sector,pos,
- LBA2cylinder(disk_car,pos),LBA2head(disk_car,pos),LBA2sector(disk_car,pos));
- if(nbr_sector>8)
- {
- data->nbr_read+=nbr_sector;
- return data->disk_car->read(data->disk_car,nbr_sector,nom_buffer,pos);
- }
- if(pos!=old_pos)
- {
- res=data->disk_car->read(data->disk_car,8,buffer,pos);
- data->nbr_read+=8;
- } else {
- ecrit_rapport("Cached\n");
- }
- memcpy(nom_buffer,buffer,nbr_sector*SECTOR_SIZE);
- return res;
- }
-
- static int cache_write(t_param_disk *disk_car,const unsigned int nbr_sector, const void *nom_buffer, const dword pos)
- {
- struct info_cache *data=disk_car->data;
- data->nbr_write+=nbr_sector;
- disk_car->write_used=1;
- return data->disk_car->write(data->disk_car,nbr_sector,nom_buffer,pos);
- }
-
- static int cache_clean(t_param_disk *disk_car)
- {
- if(disk_car->data)
- {
- struct info_cache *data=disk_car->data;
- ecrit_rapport("nbr_read %u, nbr_write %u\n",data->nbr_read,data->nbr_write);
- data->disk_car->clean(data->disk_car);
- FREE(data->disk_car);
- FREE(disk_car->data);
- disk_car->data=NULL;
- }
- return 0;
- }
-
- static t_param_disk *new_diskcache(t_param_disk *disk_car)
- {
- struct info_cache*data=MALLOC(sizeof(*data));
- t_param_disk *new_disk_car=MALLOC(sizeof(*new_disk_car));
- memcpy(new_disk_car,disk_car,sizeof(*new_disk_car));
- data->disk_car=disk_car;
- data->nbr_read=0;
- data->nbr_write=0;
- new_disk_car->halt_on_errors=0;
- new_disk_car->write_used=0;
- new_disk_car->data=data;
- new_disk_car->description=disk_car->description;
- new_disk_car->read=cache_read;
- new_disk_car->write=cache_write;
- new_disk_car->clean=cache_clean;
- return new_disk_car;
- }
- #endif
-